package dp.mobile.eden;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.StreamCorruptedException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Timer;
import java.util.TimerTask;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import dp.mobile.comm.ICommHandler;
import dp.mobile.comm.worker.BluetoothHandler;
import dp.mobile.eden.multiplayer.message.MessageBase;
import dp.mobile.eden.multiplayer.message.ReadyUpdate;
import dp.mobile.eden.multiplayer.message.action.ActionUpdate;
import dp.mobile.entity.saveable.SaveablePlayer;
import dp.mobile.game.GameEventListener;
import dp.mobile.game.GameTouchListener;
import dp.mobile.game.MultiplayerGame;
import dp.mobile.glwrapper.GameRenderer;
import dp.mobile.panel.PanelTouchListener;

public class MultiplayerAct extends GameActivityBase implements ICommHandler {
	public static final int MULTIPLAYER_OBJ_ID = 200;
	public static final int GAME_TOGGLE_ID = 201;
	public static final int GAME_TOGGLE_REPLY_ID = 202;
	public static final int GAME_END_ID = 203;
	public static final int PLAYER_STAT_UPDATE_ID = 204;
	
	public static final int MSG_WHAT_OBJECT_RECEIVED = 300;
	public static final int MSG_WHAT_GAME_TOGGLE = 301;
	public static final int MSG_WHAT_GAME_TOGGLE_REPLY = 302;
	public static final int MSG_WHAT_GAME_END = 303;
	public static final int MSG_WHAT_PLAYER_STAT_UPDATE = 304;
	
	private static final int MSG_WHAT_HIDE_TUTORIAL_PANEL = 400;
	
	private static final int STATUS_WAITING = 0;
	private static final int STATUS_STARTED = 1;
	private static final int STATUS_PAUSED = 2;
	private static final int STATUS_ENDING = 3;
	private static final int STATUS_ENDED = 4;
	
	private boolean isStarted = false;
	private Button mStartGameButton;
	private long mStartCalibration = 0;
	private boolean isPaused = false;
	private AlertDialog mPassiveAlertDialog;
	
	private int mStatus = STATUS_WAITING;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.game);
		
		mStartGameButton = (Button) findViewById(R.id.main_image);
		mStartGameButton.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if (((MultiplayerGame)mGame).isServer())
					serverStartGame();
			}
		});
		
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage("Opponent is pausing").setCancelable(false);
		mPassiveAlertDialog = builder.create();
		
		// initialize game
		boolean isServer = getIntent().getExtras().getBoolean(InitiateMultiplayerAct.EXTRA_IS_SERVER , false);
		//long propDelay = getIntent().getExtras().getLong(InitiateMultiplayerAct.EXTRA_PROP_DELAY , 100);
		mGame = new MultiplayerGame("m.xml" , isServer , 0);
		mGame.setListener(this);
		mGame.setSaveable(false);
		
		// initialize screen
		mSurface = (GLSurfaceView)findViewById(R.id.game_screen);
		mSurface.setRenderer(GameRenderer.instance(this, mGame));
		
		//initialize components
		initComp();
		
		if (isServer) {
			mTutorialTxtView.setTextColor(Color.BLUE);
			showTutorialPanel("You are on BLUE side");
			
			mElectricityCount.setTextColor(Color.BLUE);
			mDefenseCount.setTextColor(Color.BLUE);
			mComponent0Count.setTextColor(Color.BLUE);
			mComponent1Count.setTextColor(Color.BLUE);
			mComponent2Count.setTextColor(Color.BLUE);
		}
		else {
			mTutorialTxtView.setTextColor(Color.RED);
			showTutorialPanel("You are on RED side");
			
			mElectricityCount.setTextColor(Color.RED);
			mDefenseCount.setTextColor(Color.RED);
			mComponent0Count.setTextColor(Color.RED);
			mComponent1Count.setTextColor(Color.RED);
			mComponent2Count.setTextColor(Color.RED);
		}
		
		// touch handling
		mGameTouchListener	= new GameTouchListener(mGame);
		mPanelTouchListener	= new PanelTouchListener(this, mGame, mTransparentPanel);
		setListener();
		setPausePanelListeners();
		
		BluetoothHandler.getInstance().setEventHandler(this);
		initPreparation();
		//mAvailableTowers = null;
	}
	
	private void initPreparation() {
		mPausePanel.setVisibility(View.VISIBLE);
		mEndGameButton.setVisibility(View.GONE);
		mSaveGameButton.setVisibility(View.GONE);
		if (((MultiplayerGame)mGame).isServer())
			mResumeGameButton.setText("Start Game");
		else
			mResumeGameButton.setText("Waiting server");
	}
	
	private void initGameStart() {
		mResumeGameButton.setText("Resume Game");
		mEndGameButton.setVisibility(View.VISIBLE);
		mPausePanel.setVisibility(View.GONE);
		
		Timer tHideTimer = new Timer();
		tHideTimer.schedule(new TimerTask() {	
			@Override
			public void run() {
				mMultiplayerHandler.sendEmptyMessage(MSG_WHAT_HIDE_TUTORIAL_PANEL);
			}
		}, 5000);
	}
	
	@Override
	protected void setPausePanelListeners() {
		mResumeGameButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (isStarted) {
					BluetoothHandler.getInstance().sendObjectId(GAME_TOGGLE_ID);
					resumeGame();
					mPausePanel.setVisibility(View.GONE);
				}
				else {
					if (((MultiplayerGame)mGame).isServer())
						serverStartGame();
				}
			}
		});
		
		mEndGameButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				BluetoothHandler.getInstance().sendObjectId(GAME_END_ID);
				mGame.endGame();
				mPausePanel.setVisibility(View.GONE);
			}
		});
	}
	
	public void serverStartGame() {
		if (!isStarted) {
			ReadyUpdate m = new ReadyUpdate(0);
			BluetoothHandler.getInstance().sendObjectId(MULTIPLAYER_OBJ_ID);
			BluetoothHandler.getInstance().send(m);
			mStartCalibration = System.currentTimeMillis();
		}
	}
	
	
	public void clientStartGame() {
		if (!isStarted) {
			ReadyUpdate m = new ReadyUpdate(0);
			BluetoothHandler.getInstance().sendObjectId(MULTIPLAYER_OBJ_ID);
			BluetoothHandler.getInstance().send(m);
			
			mGame.start();
			isStarted = true;
			
			initGameStart();
		}
	}
	
	@Override
	public void onResume() {
		super.onResume();
		mSurface.onResume();
		mGame.onResume();
	}
	
	@Override
	public void onPause() {
		super.onPause();
		mSurface.onPause();
		mGame.onPause();
	}
	
	private void pauseGame() {
		isPaused = true;
		mGame.onPause();
		//mSurface.onPause();
		/*if (((MultiplayerGame)mGame).isServer()) {
			BluetoothHandler.getInstance().sendObjectId(PLAYER_STAT_UPDATE_ID);
			BluetoothHandler.getInstance().send(mGame.getPlayer().createSaveable());
		}*/
	}
	
	private void resumeGame() {
		isPaused = false;
		mGame.onResume();
	   	//mSurface.onResume();
	}
	
	
	@Override
	public void onBackPressed() {
		if (mTransparentPanel.getVisibility() == View.VISIBLE)
			mTransparentPanel.setVisibility(View.GONE);
		else {
			if (isStarted) {
				BluetoothHandler.getInstance().sendObjectId(GAME_TOGGLE_ID);
				if (mPausePanel.getVisibility() == View.VISIBLE) {
					resumeGame();
					mPausePanel.setVisibility(View.GONE);
				} else {
					pauseGame();
					mPausePanel.setVisibility(View.VISIBLE);
				}
			}
		}
	}
	
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		//BluetoothHandler.getInstance().disconnect();
	}
	
	@Override
	public void onAcceptFailed() {}
	@Override
	public void onConnectFailed() {}
	@Override
	public void onConnected() {}
	@Override
	public void onConnectionFailed() {
		Log.i("this", "CONNECTION FAILED");
		finish();
	}
	
	//MessageBase mIncomingMessage;
	
	private Queue<MessageBase> mIncomingMessages = new LinkedList<MessageBase>();
	
	private Handler mMultiplayerHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			MessageBase incomingMessage;
			
			if (msg.what == MSG_WHAT_OBJECT_RECEIVED) {
				incomingMessage = mIncomingMessages.remove();
				Log.i("this" , incomingMessage.getId() + "");
				if (incomingMessage.getId() == MessageBase.ID_ACTION_UPDATE) {
					ActionUpdate m = (ActionUpdate) incomingMessage;
					
					((MultiplayerGame)mGame).handleActionUpdateMessage(m);
				}
				else if (incomingMessage.getId() == MessageBase.ID_READY_UPDATE) {
					if (((MultiplayerGame)mGame).isServer()) {
						Log.i("this" , "READY UPDATE");
						long interval = System.currentTimeMillis() - mStartCalibration;
						((MultiplayerGame)mGame).setPropDelay(interval);
						Log.i("this" , "Interval : " + interval);
						mGame.start();
						isStarted = true;
						initGameStart();
					}
					else {
						clientStartGame();
					}
				}
			}
			else if (msg.what == MSG_WHAT_GAME_TOGGLE) {
				if (isPaused) {
					//mPassiveAlertDialog.cancel();
					mPausePanel.setVisibility(View.GONE);
					mResumeGameButton.setVisibility(View.VISIBLE);
					resumeGame();
				}
				else {
					//mPassiveAlertDialog.show();
					mPausePanel.setVisibility(View.VISIBLE);
					mResumeGameButton.setVisibility(View.GONE);
					pauseGame();
				}
			}
			else if (msg.what == MSG_WHAT_GAME_END) {
				mGame.endGame();
			}
			else if (msg.what == MSG_WHAT_HIDE_TUTORIAL_PANEL) {
				hideTutorialPanel();
			}
		}
	};

	@Override
	public void onObjectReceived(int objId, ObjectInputStream ois) {
		// TODO Auto-generated method stub
		Log.i("this2" , "GOT AN OBJECT");
		Message m = new Message();
		if (objId == MULTIPLAYER_OBJ_ID) {
			try {
				//mIncomingMessage = (MessageBase)ois.readObject();
				mIncomingMessages.add((MessageBase)ois.readObject());
				Log.i("this2" , "OBJECT READ");
				m.what = MSG_WHAT_OBJECT_RECEIVED;
			} catch (StreamCorruptedException e) {e.printStackTrace();
			} catch (IOException e) {e.printStackTrace();
			} catch (ClassNotFoundException e) {e.printStackTrace();}
		}
		else if (objId == GAME_TOGGLE_ID) {
			m.what = MSG_WHAT_GAME_TOGGLE;
		}
		else if (objId == GAME_TOGGLE_REPLY_ID) {
			m.what = MSG_WHAT_GAME_TOGGLE_REPLY;
		}
		else if (objId == GAME_END_ID) {
			m.what = MSG_WHAT_GAME_END;
		}
		/*else if (objId == PLAYER_STAT_UPDATE_ID) {
			try {
				SaveablePlayer s = (SaveablePlayer) ois.readObject();
				((MultiplayerGame)mGame).getOpponent().initFromSaveable(s);
				if (!((MultiplayerGame)mGame).isServer()) {
					BluetoothHandler.getInstance().sendObjectId(PLAYER_STAT_UPDATE_ID);
					BluetoothHandler.getInstance().send(mGame.getPlayer().createSaveable());
				}
			} catch (StreamCorruptedException e) {e.printStackTrace();
			} catch (IOException e) {e.printStackTrace();
			} catch (ClassNotFoundException e) {e.printStackTrace();}
		}*/
		
		mMultiplayerHandler.sendMessage(m);
	}
	
	@Override
	public void onDialog(String level, int wave) {
	}
	
	@Override
	public void onGameOver() {
		if (!isGameOver) {
			/*String stats = "";
			if (((MultiplayerGame)mGame).isServer())
				stats = mGame.getPlayer().getSummary() + ((MultiplayerGame)mGame).getOpponent().getSummary();
			else
				stats = ((MultiplayerGame)mGame).getOpponent().getSummary() + mGame.getPlayer().getSummary();*/
			
			BluetoothHandler.getInstance().sendObjectId(GAME_END_ID);
			SaveablePlayer p = mGame.getPlayer().createSaveable();
			
			Intent i = new Intent(this, GameOverAct.class);
			i.putExtra(EXTRA_PLAYER_STAT, p);
			i.putExtra(GameOverAct.EXTRA_MULTIPLAYER, true);
			startActivity(i);
			finish();
			isGameOver = true;
		}
	}
}
